Skip to main content

Basic Using

reducer/index.js
// 定义公共状态初始值
let initial = {
supportNum: 10,
disapprovalNum: 5,
}

export const reducer = (state = initial, action) => {
// type 操作类型
// payload 传递的值
let { type } = action
// 修改state有讲究
// return原来的state的话redux会认为你的state没有变化,从而无法记录时光旅行,快照,历史等。
// 那么react组件就认为state无变化则不更新组件
let newState = { ...state }
switch (type) {
case "INCREASE_SUPPORT_NUM":
newState.supportNum += 1
break
case "INCREASE_DISAPPROVAL_NUM":
newState.disapprovalNum += 1
break
default:
// 这里不能写,因为dispatch会被默认第一次执行,type会传递一个随机值
// 比如:@@redux/INITc.m.v.m.f.j
console.log(type)
// throw Error("type does not match")
}
// return 的内容会替换掉store容器中之前的内容
return newState
}
store/index.js
import { createStore } from "redux"
import { reducer } from "../reducer"

const store = createStore(reducer)

export default store
components/main.jsx
import React from "react"
import Main from "./demo1.vote.main"
import Footer from "./demo1.vote.footer"

const Demo = () => {
return (
<div>
<Main />
<Footer />
</div>
)
}

export default Demo
coponents/main.js
import React, { useState, useEffect, useCallback } from "react"
// 这里实际上不应该直接导入store使用,
// 应该使用context上下文,让store全局只有唯一一份
// 使用的时候从上下文中获取,这里忽略演示代码
import store from "./store"

const Main = () => {
// 从store中获取公共数据
let { supportNum, disapprovalNum } = store.getState()

// 1.创建一个state变量,用来触发render
let [x, setX] = useState(0)

useEffect(() => {
// 2.订阅store的变化,每次都需要重新订阅
// 因为每次执行函数,都是拿的第一次函数闭包中的x=0
let unsubscribe = store.subscribe(() => {
setX(x + 1)
})
return () => {
// 3.上一次执行完毕后,调用取消订阅
unsubscribe()
}
}, [x]) // 如果是[]的话只能执行一次,释放了,就不会再订阅了

/**
* 方法二
*/
useEffect(() => {
store.subscribe(() => {
// 每次都设置一个随机值
// 那视图必然要更新,就不依赖X的变化了
// 第一种方案需要依赖X,取到的永远都是第一次函数上下文中的x=0,导致视图永远不会render
setX(Math.random())
})
}, [])

return (
<div>
<div>支持数:{supportNum}</div>
<div>反对数:{disapprovalNum}</div>
</div>
)
}
export default Main
components/footer.js
import React from "react"
// 这里实际上不应该直接导入store使用,
// 应该使用context上下文,让store全局只有唯一一份
// 使用的时候从上下文中获取,这里忽略演示代码
import store from "./store"

class Footer extends React.Component {
increaseSupportNum = () => {
// 调用dispatch方法,触发调用reducer方法
store.dispatch({
type: "INCREASE_SUPPORT_NUM",
})
}
increaseDisapprovalNum = () => {
store.dispatch({
type: "INCREASE_DISAPPROVAL_NUM",
})
}

/**
* 函数组件中,组件首次加载完成后
* 订阅redux的store变化,强制更新组件
*/
componentDidMount() {
store.subscribe(() => {
this.forceUpdate()
})
}

render() {
let { supportNum, disapprovalNum } = store.getState()
return (
<div>
<div>总计人数:{supportNum + disapprovalNum}</div>
<button onClick={this.increaseSupportNum}>支持</button>
&nbsp;
<button onClick={this.increaseDisapprovalNum}>反对</button>
</div>
)
}
}

export default Footer